
//
// 130419 - AH - Created.
// 130609 - AH - Changed related to XmlValidator may return parse result.
//

package org.japril.servlet.xmlservlet;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.japril.jutil.SaxUtil;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * <p>
 *   {@link XmlValidator} that parses (and so will report syntax errors) and
 *   look for told about parameters that may then be fetched by
 *   {@link #getAttribute(String)}.
 * </p>
 * @author Arne Halvorsen (AH)
 */
public class DefaultXmlValidator implements XmlValidator 
{
  private boolean m_nameSpaceAware=false;
  
  private boolean m_validate=false;
  
  private final Set<String> m_lookfor=new HashSet<String>();
  
  private final Map<String, String> m_attr=new HashMap<String, String>();
  
  /**
   * <p>
   *   Constructor.
   * </p>
   */
  public DefaultXmlValidator(){}
  
  private DefaultHandler m_h=new DefaultHandler()
  {
    // Specified in ContentHandler.
    public void startElement(String uri, String lname, String qName,
      Attributes attrs) throws SAXException 
    {
      int n=attrs.getLength();
      for (int i=0; i<n; i++)
      {
        String name=attrs.getLocalName(i);
        if (m_lookfor.contains(name)) 
        {
          String val=attrs.getValue(i);
          m_attr.put(name, val);
        }
      }
    }
  };
  
  // Specified in XmlValidator.
  public final Object validate(InputStream is) throws IOException
  {
    SAXParserFactory f=SAXParserFactory.newInstance();
    f.setNamespaceAware(m_nameSpaceAware);
    f.setValidating(m_validate);
    
    try
    {
      SAXParser parser=f.newSAXParser();
      m_attr.clear();
      parser.parse(is, m_h);
      return null;
    }
    catch (ParserConfigurationException pcx)
    {
      throw SaxUtil.getIOException(pcx);
    }
    catch (SAXException saxx)
    {
      throw SaxUtil.getIOException(saxx);
    }
  }

  // Specified in XmlValidator.
  //public final Object validate(String xml) throws IOException
  public final void validate(String xml) throws IOException
  {
    ByteArrayInputStream bais=new ByteArrayInputStream(xml.getBytes());
    validate(bais);
    //return null;
  }

  // Specified in XmlValidator.
  public final String getAttribute(String name)
  {
    if (name==null)
    {
      throw new NullPointerException();
    }
    
    return m_attr.get(name);
  }
  
  /**
   * <p>
   *   Sets if parsing is namespace aware.
   * </p>
   * @param v {@code true} if is, {@code false} if is not.
   */
  public final void setNamespaceAware(boolean v){ m_nameSpaceAware=v; }
  
  /**
   * <p>
   *   Sets if parsing validated.
   * </p>
   * @param v {@code true} if do, {@code false} if do not.
   */
  public final void setValidate(boolean v){ m_validate=v; }
  
}
